package com.bdzl.gateway.config;

import com.bdzl.api.LoginCheckApi;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;

/**
 * 自定义过滤器，向下游服务请求加header认证信息.
 * 与敏感头(设置向内部服务不传递哪些header正好相反)，
 * 这种方式好像不能传递名称为 Authorization,Cookie,Set-Cookie 的请求头，这三个传递不到下游服务，这三个由敏感头管理，只能传递token这种自定义的头
 */
@Slf4j
@Setter
@Getter
@Component
//@ConfigurationProperties("org.my.jwt")
public class AuthFilter implements GlobalFilter , Ordered {
	@Autowired
	private LoginCheckApi loginCheckApi;

	@Value("${whiteList.skipAuthUrls}")
	private List<String> skipAuthUrls;

	private ObjectMapper objectMapper;

	public AuthFilter(ObjectMapper objectMapper) {
		this.objectMapper = objectMapper;
	}

	/**
	 * 过滤器
	 *
	 * @param exchange
	 * @param chain
	 * @return
	 */
	@Override
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		String url = exchange.getRequest().getURI().getPath();
		ServerHttpRequest request = this.getHttpServletRequest(exchange);
		System.out.println("------------"+StringUtils.join(skipAuthUrls,","));
		//跳过不需要验证的路径
		/*boolean t = false;
		if (null != skipAuthUrls) {
			for (String skipAuthUrl : skipAuthUrls) {
				if (url.contains(skipAuthUrl)){
					t = true;
					break;
				}
			}
		}*/
		if (skipAuthUrls.contains(url)){
			return chain.filter(exchange);
		}
		//获取token
		String token = exchange.getRequest().getHeaders().getFirst("X-Access-Token");
		ServerHttpResponse resp = exchange.getResponse();
		if (StringUtils.isBlank(token)) {
			//没有token
			return authErro(resp, "请登陆!");
		} else {
			//有token
				// 调用统一认证接口，判断是否登录 && 判断是否有功能权限
				// 校验token
				Object check = loginCheckApi.checkPermission(token, url);
			if(check instanceof HashMap) {
					HashMap result = (HashMap) check;
				System.out.println("-------"+result);
				System.out.println("-------"+result.get("respCode"));
				Object o = result.get("respCode");
				if (o!=null){
					if("0000".equals(result.get("respCode"))) {
						System.out.println("放行！");
						return chain.filter(exchange);
					}else if ("0002".equals(result.get("respCode"))){
						return authErro(resp, "没有权限！");
					}else {
						return authErro(resp, "登录失效，请重新登录!");
					}
				}else {
					return authErro(resp, "认证失败!");
				}
				}else {
					return authErro(resp, "没有权限！");
				}
		}
	}

	/**
	 * 认证错误输出
	 *
	 * @param resp 响应对象
	 * @param mess 错误信息
	 * @return
	 */
	private Mono<Void> authErro(ServerHttpResponse resp, String mess) {
		resp.setStatusCode(HttpStatus.UNAUTHORIZED);
		resp.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
		Resp<String> returnData = new Resp<>(org.apache.http.HttpStatus.SC_UNAUTHORIZED, mess, mess);
		String returnStr = "";
		try {
			returnStr = objectMapper.writeValueAsString(returnData);
		} catch (JsonProcessingException e) {
			log.error(e.getMessage(), e);
		}
		DataBuffer buffer = resp.bufferFactory().wrap(returnStr.getBytes(StandardCharsets.UTF_8));
		return resp.writeWith(Flux.just(buffer));
	}

	/*private String getUrl(ServerHttpRequest request) {
		// 获取到请求的相关数据  uri是斜杠开头
		String uri = request.getRequestURI().toLowerCase().replaceAll("//", "/");
		String method = request.getMethod().toLowerCase();
		return method.concat(uri);
	}*/

	private ServerHttpRequest getHttpServletRequest(ServerWebExchange exchange) {
		try {
//			ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
			ServerHttpRequest request = exchange.getRequest();
			return request;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	@Override
	public int getOrder() {
		return -100;
	}

}
